// 
//  Copyright © 2009 Jiří Zárevúcky <zarevucky.jiri@gmail.com>
// 
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as
//  published by the Free Software Foundation, either version 3 of the
//  License, or (at your option) any later version.
// 
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Affero General Public License for more details.
// 
//  You should have received a copy of the GNU Affero General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
// 
// 


using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;

using Galaxium.Protocol.Xmpp.Library.Xml;

namespace Galaxium.Protocol.Xmpp.Library.Extensions
{
	public class SearchResultItem
	{
		public SearchResultItem ()
		{
			_fields = new Dictionary<string, object> ();
		}
		
		public SearchResultItem (Element source, SearchResultHeader header) : this ()
		{
			if (source.Name != "item")
				throw new ArgumentException ();
			
			var fields = new Dictionary<string, List<string>> ();
			
			foreach (var field in source) {
				if (field.Name != "field") continue;
				var list = new List<string> ();
				foreach (var val in field.EachChild ("value"))
					list.Add (val.Text);
				fields [field ["var"]] = list;
			}
			
			foreach (DataField field in header) {
				
				switch (field.Type) {
				case DataFieldType.Boolean:
					_fields [field.Identifier] = Boolean.Parse (fields [field.Identifier][0]);
					break;
				
				case DataFieldType.Fixed:
				case DataFieldType.TextSingle:
				case DataFieldType.Hidden:
				case DataFieldType.TextPrivate:
				case DataFieldType.ListSingle:
					_fields [field.Identifier] = fields [field.Identifier][0];
					break;

				case DataFieldType.TextMulti:
				case DataFieldType.ListMulti:
					_fields [field.Identifier] = fields [field.Identifier];
					break;
				
				case DataFieldType.JidSingle:
					_fields [field.Identifier] = (JabberID) fields [field.Identifier][0];
					break;
				
				case DataFieldType.JidMulti:
					var list = new List<JabberID> ();
					foreach (var jid in fields [field.Identifier])
						list.Add (jid);
					_fields [field.Identifier] = list;
					break;
				}
			}
		}
		
		public Dictionary<string, object> _fields;
		
		public void SetBool (string field, bool value)
		{
			_fields [field] = value;
		}
		
		public void SetString (string field, string value)
		{
			_fields [field] = value;
		}
		
		public void SetString (string field, string value, bool multiline)
		{
			if (multiline)
				_fields [field] = value.Split ('\n');
			else
				_fields [field] = value.Replace ('\n', ' ');
			
		}
		
		public void SetStrings (string field, IEnumerable<string> values)
		{
			_fields [field] = values;
		}
		
		public void SetJid (string field, JabberID jid)
		{
			_fields [field] = jid;
		}
		
		public void SetJids (string field, IEnumerable<JabberID> jids)
		{
			_fields [field] = jids;
		}
		
		private object GetValue (string field)
		{
			object value;
			if (_fields.TryGetValue (field, out value)) return value;
			else return null;
		}
		
		public bool GetBool (string field)
		{
			return (bool) GetValue (field);
		}
		
		public string GetString (string field)
		{
			var value = GetValue (field);
			if (value is string) return value as string;
			var sb = new StringBuilder ();
			foreach (var s in (IEnumerable<string>) value)
				sb.Append (s + '\n');
			sb.Remove (sb.Length - 1, 1);
			return sb.ToString ();
		}
		
		public IEnumerable<string> GetStrings (string field)
		{
			return (IEnumerable<string>) GetValue (field);
		}
		
		public JabberID GetJid (string field)
		{
			return (JabberID) GetValue (field);
		}
		
		public IEnumerable<JabberID> GetJids (string field)
		{
			return (IEnumerable<JabberID>) GetValue (field);
		}
		
		public Element ToXml ()
		{
			var e = new Element ("item");
			
			foreach (var field in _fields) {
				var f = new Element ("field");
				f ["var"] = field.Key;
				
				if (field.Value is IEnumerable)
					foreach (var value in field.Value as IEnumerable)
						f.AppendChild (new Element ("value").SetText (value.ToString ()));
				else
					f.AppendChild (new Element ("value").SetText (field.Value.ToString ()));
				
				e.AppendChild (f);
			}
			
			return e;
		}
	}
}
